
/*
 * Copyright (c) 2013.
 * 游戏服务器核心代码编写人陈磊拥有使用权
 * 联系方式：E-mail:13638363871@163.com ;qq:502959937
 * 个人博客主页：http://my.oschina.net/chenleijava
 */

package com.dc.gameserver.serverCore.controller.handleController.pvpCoreController;

import com.dc.gameserver.baseConfig.Config;
import com.dc.gameserver.exceptions.logicException;
import com.dc.gameserver.hardCode.CardType;
import com.dc.gameserver.hardCode.playerGameStatus;
import com.dc.gameserver.proto.gameserverprotoVo.*;
import com.dc.gameserver.serverCore.controller.AbstractController.AbstractController;
import com.dc.gameserver.serverCore.controller.AbstractController.IController;
import com.dc.gameserver.serverCore.service.battle.GameFormula;
import com.dc.gameserver.serverCore.service.cardModule.Card;
import com.dc.gameserver.serverCore.service.cardModule.CardBox;
import com.dc.gameserver.serverCore.service.cardModule.CardBoxManager;
import com.dc.gameserver.serverCore.service.character.GameCharacter;
import com.dc.gameserver.serverCore.service.character.PlayerInstance;
import com.dc.gameserver.serverCore.service.managerService.ThreadPoolManager;
import com.google.protobuf.MessageLite;
import javolution.util.FastTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author : 石头哥哥
 *         Project : LandlordsServer
 *         Date: 13-6-4
 *         Time: 上午11:49
 *         Connect: 13638363871@163.com
 *         packageName: Server.ServerCore.Controller
 */
@Service
public class handleOutCardController extends AbstractController {

    private static final Logger LOGGER= LoggerFactory.getLogger(handleOutCardController.class);

    /**
     */
    @Override
    public void PostConstruct() {
        int ID= outCardRequest.msgID.ID_VALUE;
       GAME_CONTROLLERS[ID]=this;   //业务逻辑处理引用
       IController.MESSAGE_LITE[ID]= outCardRequest.getDefaultInstance();   //解析的pb实体类型
    }
     /**
     * messageLite数据结构体分发
     * @param messageLite
     * @param player
     * @throws Exception
      * 玩家出牌的动作：1.正常出牌，2：放弃出牌；
      *
     */
    @Override
    public void DispatchMessageLit(MessageLite messageLite, final PlayerInstance player) throws Exception {
        /**
         * 法力值，出牌类型，最大出牌数量规则等，前端根据规则以及后端推送更新的数据进行过滤
         */
        final CardBox cardBox= CardBoxManager.getCardBoxByID(player.getCardBoxID());
        int result=0;

        /**临时出牌列表（判定玩家是否都出牌到预出牌临时区域）*/
        FastTable<GameCharacter> checkList=cardBox.getCheckOutCardPlayerList();

        //1.出牌类型异常，2.放弃出牌操作成功，3.出牌操作成功；4.出牌张数，5.出牌是非法牌；6.出技能牌失败，法力值不够  ;7.防御失败，法力值不足
        if (cardBox!=null){
            outCardRequest outCardRequest= (outCardRequest) messageLite;
            List<netCardVO> netCardVOList=outCardRequest.getNetCardVOList();

            boolean giveOut=outCardRequest.getGiveOut();
            /**
             *  类型检查
             */
           if (!giveOut){
               int  cardType= netCardVOList.get(0).getCardNum();
               if (netCardVOList.size()>=1){
                   for (netCardVO netCardVO:netCardVOList){
                       if (netCardVO.getCardNum()!=cardType){
                           result=1;
                           outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                           builder.setResult(result);
                           player.DirectSend(wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
                           return;
                       }
                   }
               }

               /**
                * 检查出牌技能，防御等 法力值是否足够
                */
                int cardNum= netCardVOList.size();
                //magic check
               if (cardType==CardType.MAGIC_TYPE.getType()){
                   int magic= GameFormula.computeMagicUse(player);
                   if (player.getCurrentMagic()<magic){
                       outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                       result=6;
                       builder.setResult(result);    //6.出技能牌失败，法力值不够
                       player.DirectSend(CardBox.wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
                       return ;
                   }
               }
               //defence check
               if (cardType==CardType.DEFENCE_TYPE.getType()){
                   int magic= GameFormula.ComputeDeffenceLoss(player,cardNum);
                   if (player.getCurrentMagic()<magic){
                       outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                       result=7;
                       builder.setResult(result);    //7.出防御牌失败，法力值不够
                       player.DirectSend(CardBox.wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
                       return;
                   }
               }

               /**
                * 牌的张数验证
                */
               if (netCardVOList.size()> player.getMaxOutCard()){
                   result=4;
                   outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                   builder.setResult(result);
                   player.DirectSend(wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
                   return;
               }

               /**
                * 验证出牌的合法性
                */
               if (!player.checkCard(netCardVOList)){
                   //出牌不合法
                   result=5;
                   outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                   builder.setResult(result);
                   player.DirectSend(wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
//                   player.getChannel().close();   // close channel
                   return;
               }
           }

            player.setActionOutCard(true);//happen out  card action before Timer_out_task!
            /****出牌合法,正常逻辑处理***/
            /**
             * 检查眩晕     system active
             */
            for (GameCharacter pp:checkList){
                int DizzinessTimes= pp.getDizzinessTimes();
                if (DizzinessTimes!=0){   //眩晕状态，被通知不出牌
                    DizzinessTimes=DizzinessTimes-1;
                    pp.setDizzinessTimes(DizzinessTimes);
                    if (pp.getDizzinessTimes()<=0){
                        pp.setDizzinessTimes(0);
                        dizzniessResponse.Builder builder=dizzniessResponse.newBuilder();
                        builder.setPlayerID(pp.getID());
                        builder.setResult(playerGameStatus.undizziness.getStatus());      //同步，pp解除眩晕
                        cardBox.submitMessageToEveryOne(wrappedBufferShort(dizzniessResponse.msgID.ID_VALUE, builder.build()));
                    }
                    checkList.remove(pp);
                }
            }

            //放弃出牌  ，注意不是处于眩晕状态  主动放弃出牌
            if(giveOut){
                giveOutCard.Builder builder=giveOutCard.newBuilder();
                builder.setPlayerID(player.getID());
                if (!checkList.isEmpty()){
                     for (GameCharacter p:checkList){
                         if (player.getID()!=p.getID()){       // 通知另一个玩家的玩家 ,对手弃牌
                             p.DirectSend(wrappedBufferShort(giveOutCard.msgID.ID_VALUE,builder.build()));
                         }
                     }
                }
                result=2;
                checkList.remove(player);
                player.setGiveOut(true);    //flag 放弃出牌
                if (checkAllPlayerGiveOut(cardBox)){
                    //notify next round
                    AllPlayerGiveOutAndNotifyOutcardForNext(cardBox);
                    return;
                }
            }

            //添加牌
            if (!giveOut&&!netCardVOList.isEmpty()) {
                for (netCardVO netCardVO:netCardVOList){
                    /**清理玩家当前的牌库*/
                    Card card= player.removeIncardlib(netCardVO.getCardNum(), netCardVO.getCardCount());
                    if (card==null){
                        LOGGER.debug("card must be not empty ,check out!!!",new NullPointerException("card  is null"));
                    }
                    /**添加到临时出牌库*/
                    if (card!=null)player.addOutCard(card);
                }
                /**添加玩家到出牌列表中 ready for logic dispatcher***/
                cardBox.getTempOutCardPlayerList().addLast(player);
                /**set card type 出牌类型 便于后期逻辑处理计算 额 出牌类型应该必须一致（前端验证）**/
                int cardNum=netCardVOList.get(0).getCardNum();
                /**设置牌类型 牌类型做准备***/
                player.setCardType(CardType.getTypeByFlg(cardNum));
                checkList.remove(player);
                result=3 ;
            }

            outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
            builder.setResult(result);
            player.DirectSend(wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
            outCardRequest=null;        // by GC collection

            /***
             * 检查出牌是否完毕
             */
            if (checkList.size()==0){
                if (Config.DEFAULT_VALUE.SERVER_VALUE.useMultleThread){
                   final Runnable runnable=new Runnable() {
                       @Override
                       public void run() {
                           CardBoxManager.coreLogic(cardBox);
                       }
                    } ;
                   ThreadPoolManager.getInstance().executeCalculate(runnable);
                } else {
                    CardBoxManager.coreLogic(cardBox);
                }
            }
        }else {
           throw  new logicException("逻辑异常，请仔细检查！cardBoxManager must not be null");
        }
    }


    /**
     * 检查所有玩家是否放弃
     * @param cardBox
     * @return
     */
    public static boolean checkAllPlayerGiveOut(CardBox cardBox){
        boolean status=true;
        FastTable <GameCharacter> playerInstanceFastTable=cardBox.getInGamePlayerList();
        for (GameCharacter pp:playerInstanceFastTable){
            if (!pp.isGiveOut()){
                 status=false;
            }
        }
        return status;
    }

    /**
     *    所有人放弃出牌，通知下一回合开始
     */
    private  void AllPlayerGiveOutAndNotifyOutcardForNext(CardBox cardBox){
        cardBox.flushBloodAndMagic();
        FastTable <GameCharacter> InGamePlayerList=cardBox.getInGamePlayerList();
        for (GameCharacter gameCharacter:InGamePlayerList){
            gameCharacter.clearRoundResource();  //清空player资源  for next

            cardBox.getCheckOutCardPlayerList().add(gameCharacter);//ready for next
            //new card
            Card[] cards=cardBox.getOutCardsAndRecoveryMagic(gameCharacter);
            synResetRoundCardResponse.Builder builder=synResetRoundCardResponse.newBuilder();
            if (cards!=null){
                for (com.dc.gameserver.serverCore.service.cardModule.Card card:cards){
                    netCardVO.Builder netCardBuilder=netCardVO.newBuilder();
                    netCardBuilder.setCardNum(card.getType());//编号
                    netCardBuilder.setCardCount(card.getCount());//点数
                    builder.addNewList(netCardBuilder.build()) ;
                }
            }
            //all card
            FastTable<Card> PlayerCardList=gameCharacter.getCardlib();
            for (com.dc.gameserver.serverCore.service.cardModule.Card card:PlayerCardList){
                netCardVO.Builder netCardBuilder=netCardVO.newBuilder();
                netCardBuilder.setCardNum(card.getType());//编号
                netCardBuilder.setCardCount(card.getCount());//点数
                builder.addAllList(netCardBuilder.build());
            }
            builder.setPlayerID(gameCharacter.getID());
            gameCharacter.DirectSend(CardBox.wrappedBufferShort(synResetRoundCardResponse.msgID.ID_VALUE, builder.build()));
        }

        FastTable<GameCharacter> playerInstances=new FastTable<GameCharacter>();
        int round=cardBox.RoundCount();
        for (GameCharacter player:InGamePlayerList){
            if (player.getDizzinessTimes()==0){           //可以出牌
                player.setActionOutCard(false);
                playerInstances.add(player);
                CardBoxManager.notifyOutCards(player, true,round);
            } else {
                player.setActionOutCard(true);
                CardBoxManager.notifyOutCards(player, false,round);//不可以可以出牌
            }
        }
        if (playerInstances.size()>0){
            CardBoxManager.registerRoundOutCardTimeOutTaskAndExecutorForPVP(playerInstances);
        }else {
            playerInstances=null;
        }

    }
}
